import { _decorator, Component, director, Node } from 'cc';
import { TileMapManager } from '../Tile/TileMapManager';
import { createUINode } from '../../Utils';
import Levels, { ILevel } from '../../Levels';
import DataManager, { IRecord } from '../../Runtime/DataManager';
import { TILE_HEIGHT, TILE_WIDTH } from '../Tile/TileManager';
import { DIRECTION_ENUM, ENTITY_STATE_ENUM, ENTITY_TYPE_ENUM, EVENT_ENUM } from '../../Enums';
import EventManager from '../../Runtime/EventManager';
import { PlayerManager } from '../Player/PlayerManager';
import { WoodenSkeletonManager } from '../WoodenSkeleton/WoodenSkeletonManager';
import { DoorManager } from '../Door/DoorManager';
import { IronSkeletonManager } from '../IronSkeleton/IronSkeletonManager';
import { BurstManager } from '../Burst/BurstManager';
import { SpikesManager } from '../Spikes/SpikesManager';
import { SmokeManager } from '../Smoke/SmokeManager';
import FaderManager from '../../Runtime/FaderManager';
import { ShakeManager } from '../UI/ShakeManager';
const { ccclass, property } = _decorator;

@ccclass('BattleManager')
export class BattleManager extends Component {
    level: ILevel;
    stage: Node
    private smokeLayer: Node
    private inited: boolean = false

    onLoad() {
        DataManager.Instance.levelIndex = 1;
        EventManager.Instance.on(EVENT_ENUM.NEXT_LEVEL, this.nextLevel, this);
        EventManager.Instance.on(EVENT_ENUM.PLAYER_MOVE_END, this.checkArrived, this);
        EventManager.Instance.on(EVENT_ENUM.SHOW_SMOKE, this.generateSmoke, this);
        EventManager.Instance.on(EVENT_ENUM.RECORD_STEP, this.record, this);
        EventManager.Instance.on(EVENT_ENUM.REVOKE_STEP, this.revoke, this);
        EventManager.Instance.on(EVENT_ENUM.RESTART, this.inintLevel, this);
        EventManager.Instance.on(EVENT_ENUM.OUT, this.out, this);
    }


    start() {
        this.generateStage();
        this.inintLevel();
    }

    /**初始化关卡 */
    async inintLevel() {
        const level = Levels[`level${DataManager.Instance.levelIndex}`]
        if (level) {
            if (this.inited) {
                await FaderManager.Instance.fadeIn()
            } else {
                await FaderManager.Instance.mask()
            }
            this.clearLevel();

            this.level = level;

            DataManager.Instance.mapInfo = this.level.mapInfo;
            DataManager.Instance.mapRowCount = this.level.mapInfo.length || 0;
            DataManager.Instance.mapColumnCount = this.level.mapInfo[0]?.length || 0;

            await Promise.all([
                this.generateTileMap(),
                this.generateBursts(),
                this.generateSpikes(),
                this.generateSmokeLayer(),
                this.generateDoor(),
                this.generateEnemy(),
                this.generatePlayer(),
            ])

            await FaderManager.Instance.fadeOut()
            this.inited = true
        } else {
            this.out()
        }
    }

    /** 下一关 */
    nextLevel() {
        DataManager.Instance.levelIndex++;
        this.inintLevel();
    }

    /** 清除关卡 */
    clearLevel() {
        this.stage.destroyAllChildren();
        DataManager.Instance.reset()
    }

    generateStage() {
        this.stage = createUINode();
        this.stage.setParent(this.node);
        this.stage.addComponent(ShakeManager)
        this.stage.setSiblingIndex(2)
    }

    async generateTileMap() {
        const tileMap = createUINode();
        tileMap.setParent(this.stage);
        const tileMapManager = tileMap.addComponent(TileMapManager);
        await tileMapManager.init();
        this.adaptPos();
    }


    /**生成敌人 */
    async generateEnemy() {
        const promises = []
        for (let i = 0; i < this.level.enemies.length; i++) {
            const enemy = this.level.enemies[i];
            //木头人
            const node = createUINode();
            node.setParent(this.stage);
            const EnemyManager = enemy.type === ENTITY_TYPE_ENUM.WOODEN_SKELETON ? WoodenSkeletonManager : IronSkeletonManager;
            const enemyManager = node.addComponent(EnemyManager);
            promises.push(enemyManager.init(enemy))
            DataManager.Instance.enemies.push(enemyManager)
        }
        await Promise.all(promises)
    }

    /**生成门 */
    async generateDoor() {
        const door = createUINode();
        door.setParent(this.stage);
        const doorManager = door.addComponent(DoorManager);
        await doorManager.init(this.level.door);
        DataManager.Instance.door = doorManager
    }

    /** 生成玩家 */
    async generatePlayer() {
        const player = createUINode();
        player.setParent(this.stage);
        const playerManager = player.addComponent(PlayerManager);
        await playerManager.init(this.level.player);
        DataManager.Instance.player = playerManager
        EventManager.Instance.emit(EVENT_ENUM.PLAYER_BORN, true)
    }
    /**生成碎裂地块 */
    async generateBursts() {
        const promises = []
        for (let i = 0; i < this.level.bursts.length; i++) {
            const burst = this.level.bursts[i];
            //木头人
            const node = createUINode();
            node.setParent(this.stage);
            const burstManager = node.addComponent(BurstManager);
            promises.push(burstManager.init(burst))
            DataManager.Instance.bursts.push(burstManager)
        }
        await Promise.all(promises)
    }

    /**生成地刺 */
    async generateSpikes() {
        const promises = []
        for (let i = 0; i < this.level.spikes.length; i++) {
            const spike = this.level.spikes[i];
            //木头人
            const node = createUINode();
            node.setParent(this.stage);
            const spikesManager = node.addComponent(SpikesManager);
            promises.push(spikesManager.init(spike))
            DataManager.Instance.spikes.push(spikesManager)
        }
        await Promise.all(promises)
    }

    /**生成烟雾 */
    async generateSmoke(x: number, y: number, direction: DIRECTION_ENUM) {
        const smokeItem = DataManager.Instance.smokes.find(smoke => smoke.state === ENTITY_STATE_ENUM.DEATH)
        if (smokeItem) {
            console.log("smoke pool");
            smokeItem.x = x
            smokeItem.y = y
            smokeItem.direction = direction
            smokeItem.state = ENTITY_STATE_ENUM.IDLE
            smokeItem.node.setPosition(x * TILE_WIDTH - TILE_WIDTH * 1.5, -y * TILE_HEIGHT + TILE_HEIGHT * 1.5)
        } else {
            const smoke = createUINode();
            smoke.setParent(this.smokeLayer);
            const smokeManager = smoke.addComponent(SmokeManager);
            await smokeManager.init({
                x,
                y,
                direction,
                type: ENTITY_TYPE_ENUM.SMOKE,
                state: ENTITY_STATE_ENUM.IDLE
            });
            DataManager.Instance.smokes.push(smokeManager)
        }

    }

    generateSmokeLayer() {
        this.smokeLayer = createUINode()
        this.smokeLayer.setParent(this.stage)
    }

    /**检查是否到达终点 */
    checkArrived() {
        const { x: playerX, y: playerY } = DataManager.Instance.player
        const { x: doorX, y: doorY, state: doorState } = DataManager.Instance.door
        if (doorX === playerX && doorY === playerY && doorState === ENTITY_STATE_ENUM.DEATH) {
            EventManager.Instance.emit(EVENT_ENUM.NEXT_LEVEL)
          }
    }


    /**适配屏幕方法 */
    adaptPos() {
        const { mapRowCount, mapColumnCount } = DataManager.Instance;
        const disX = TILE_WIDTH * mapRowCount / 2;
        const disY = TILE_HEIGHT * mapColumnCount / 2 + 80;
        this.stage.getComponent(ShakeManager).stopShake()
        this.stage.setPosition(-disX, disY);
    }

    /**记录数据*/
    record() {
        const item: IRecord = {
            player: {
                x: DataManager.Instance.player.x,
                y: DataManager.Instance.player.y,
                type: DataManager.Instance.player._type,
                direction: DataManager.Instance.player.direction,
                state:
                    DataManager.Instance.player.state === ENTITY_STATE_ENUM.IDLE ||
                        DataManager.Instance.player.state === ENTITY_STATE_ENUM.DEATH ||
                        DataManager.Instance.player.state === ENTITY_STATE_ENUM.AIR_DEATH
                        ? DataManager.Instance.player.state
                        : ENTITY_STATE_ENUM.IDLE
            },
            door: {
                x: DataManager.Instance.door.x,
                y: DataManager.Instance.door.y,
                type: DataManager.Instance.door._type,
                direction: DataManager.Instance.door.direction,
                state: DataManager.Instance.door.state
            },
            enemies: DataManager.Instance.enemies.map(enemy => ({
                x: enemy.x,
                y: enemy.y,
                type: enemy._type,
                direction: enemy.direction,
                state: enemy.state
            })),
            bursts: DataManager.Instance.bursts.map(burst => ({
                x: burst.x,
                y: burst.y,
                type: burst._type,
                direction: burst.direction,
                state: burst.state
            })),
            spikes: DataManager.Instance.spikes.map(spike => ({
                x: spike.x,
                y: spike.y,
                type: spike._type,
                count: spike.count,
            })),
        }
        DataManager.Instance.records.push(item)
    }

    /**撤销 */
    revoke() {
        const item = DataManager.Instance.records.pop()
        if (item) {
            DataManager.Instance.player.x = DataManager.Instance.player.targetX = item.player.x
            DataManager.Instance.player.y = DataManager.Instance.player.targetY = item.player.y
            DataManager.Instance.player.direction = item.player.direction
            DataManager.Instance.player.state = item.player.state

            DataManager.Instance.door.x = item.door.x
            DataManager.Instance.door.y = item.door.y
            DataManager.Instance.door.direction = item.door.direction
            DataManager.Instance.door.state = item.door.state

            for (let i = 0; i < DataManager.Instance.enemies.length; i++) {
                const enemy = item.enemies[i];
                DataManager.Instance.enemies[i].x = enemy.x
                DataManager.Instance.enemies[i].y = enemy.y
                DataManager.Instance.enemies[i].direction = enemy.direction
                DataManager.Instance.enemies[i].state = enemy.state
            }

            for (let i = 0; i < DataManager.Instance.bursts.length; i++) {
                const burst = item.bursts[i];
                DataManager.Instance.bursts[i].x = burst.x
                DataManager.Instance.bursts[i].y = burst.y
                DataManager.Instance.bursts[i].state = burst.state
            }

            for (let i = 0; i < DataManager.Instance.spikes.length; i++) {
                const spike = item.spikes[i];
                DataManager.Instance.spikes[i].x = spike.x
                DataManager.Instance.spikes[i].y = spike.y
                DataManager.Instance.spikes[i].count = spike.count
                DataManager.Instance.spikes[i]._type = spike.type
            }

        }
    }


    /**退出游戏 */
    async out() {
        await FaderManager.Instance.fadeIn(1000)
        director.loadScene("MainScene")
    }


    onDestroy() {
        EventManager.Instance.off(EVENT_ENUM.NEXT_LEVEL, this.nextLevel);
        EventManager.Instance.off(EVENT_ENUM.PLAYER_MOVE_END, this.checkArrived);
        EventManager.Instance.off(EVENT_ENUM.SHOW_SMOKE, this.generateSmoke);
        EventManager.Instance.off(EVENT_ENUM.RECORD_STEP, this.record);
        EventManager.Instance.off(EVENT_ENUM.REVOKE_STEP, this.revoke);
        EventManager.Instance.off(EVENT_ENUM.RESTART, this.inintLevel);
        EventManager.Instance.off(EVENT_ENUM.OUT, this.out);
    }
}


